package top.truehaku.generator.code.domain.model.table;

import com.google.common.collect.Sets;
import lombok.Getter;
import lombok.Setter;
import top.truehaku.generator.code.domain.model.column.Column;
import top.truehaku.generator.common.domain.Entity;
import top.truehaku.generator.common.enums.JavaType;
import top.truehaku.generator.common.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

public class Table implements Entity<Table> {

    @Getter@Setter
    private TableId tableId;

    @Getter@Setter
    private TableComment tableComment;

    private String tableSimpleName;

    @Getter@Setter
    private List<Column> columnList;

    private Class<?> baseEntity;

    public Table(TableId tableId, TableComment tableComment,List<Column> columnList) {
        this.tableId = tableId;
        this.tableComment = tableComment;
        this.columnList = columnList;
        this.tableSimpleName = tableId.getTableName();
    }

    @Override
    public boolean sameIdentityAs(Table other) {
        return other!=null&&this.tableId.sameValueAs(other.tableId);
    }


    /**
     * 获取去除可忽略前缀后的名字
     * @param negligiblePrefixes
     * @return
     */
    public void removePrefixes(Set<String> negligiblePrefixes){
        String tableName = this.tableId.getTableName();
        for (String prefix:negligiblePrefixes){
            if (tableName.startsWith(prefix)){
                this.tableSimpleName = tableName.replaceFirst(prefix,"");
            }
        }
    }

    /**
     * 获取表别名
     * @return
     */
    public String getTableAlias(){
        String[] names = this.tableId.getTableName().split("_");
        return Arrays.stream(names).map(name -> name.substring(0, 1).toLowerCase()).collect(Collectors.joining());
    }

    public String getModuleName(){
        String[] names = this.tableId.getTableName().split("_");
        return names[0].toLowerCase();
    }

    public String getLastname(){
        String[] names = this.tableId.getTableName().split("_");
        return names[names.length-1].toLowerCase();
    }

    /**
     * 表名映射实体 首字母大写
     * @return
     */
    public String getEntityName(){
        return StringUtils.toCamelCase(tableSimpleName,true);
    }

    /**
     * 表名映射实体 首字母小写
     * @return
     */
    public String getObjectName(){
        return StringUtils.toCamelCase(tableSimpleName,false);
    }

    public static void main(String[] args) {
        Table table = new Table(new TableId("core","monitor_operation_log"),new TableComment("这是注释"),null);
        System.out.println(table.getEntityName());
        table.removePrefixes(Sets.newHashSet("monitor_","system_"));
        System.out.println(table.getEntityName());
        System.out.println(table.getTableAlias());
    }

    /**
     * 实体是否需要依赖Date BigDecimal等类型
     * @param whetherPojo
     * @return
     */
    public Set<String> getImports(boolean whetherPojo){
        Set<String> imports = new HashSet<>();
        for (Column column:columnList){
            if (whetherPojo&&!column.getParentIncluded()){
                JavaType javaType = column.getColumnType().getJavaType();
                if (javaType.getReference() != null) {
                    imports.add(javaType.getReference());
                }
            }
        }
        if (whetherPojo&&containsDate()){
            imports.add(Date.class.getTypeName());
        }
//        if (imports.contains("java.util.Date")){
//            imports.add("com.fasterxml.jackson.annotation.JsonFormat");
//            imports.add("org.springframework.format.annotation.DateTimeFormat");
//        }
        return imports;
    }

    public boolean containsDate(){
        return this.columnList.stream().anyMatch(column ->(!column.getParentIncluded())&&column.getColumnType().getJavaType().equals(JavaType.DATE));
    };

    public boolean containsString(){
        return this.columnList.stream().anyMatch(column ->(!column.getParentIncluded())&&column.getColumnType().getJavaType().equals(JavaType.STRING));
    };

    public boolean containsUnique(){
        return this.columnList.stream().anyMatch(Column::getUniqueKey);
    }

    public boolean containsCombineColumn(){
        return this.columnList.stream().anyMatch(column ->column.getColumnComment().isCombine());
    }

    public Column getPrimaryColumn(){
        return this.columnList.stream().filter(Column::getPrimaryKey).findFirst().get();
    }

}
